home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / tjgold.zip / INSTALL.001 / GOLDKEY.PAS < prev    next >
Pascal/Delphi Source File  |  1995-07-12  |  32KB  |  1,261 lines

  1. {--------------------------------------------------------------------------}
  2. {                Product: TechnoJock's Turbo Toolkit                       }
  3. {                Version: GOLD                                             }
  4. {                Build:   1.01                                             }
  5. {                                                                          }
  6. {                Copyright 1986-1995  TechnoJock Software, Inc.            }
  7. {                           All Rights Reserved                            }
  8. {                          Restricted by License                           }
  9. {--------------------------------------------------------------------------}
  10.  
  11.                     {*********************************}
  12.                     {**       Unit:   GOLDKEY       **}
  13.                     {*********************************}
  14.  
  15. {++++++++++++++++++++++++++++++} unit GOLDKEY; {+++++++++++++++++++++++++++++}
  16.  
  17. {$I GOLDFLAG.INC}
  18. {$IFNDEF GOLDKEY}
  19.    {$DEFINE GOLDKEY}
  20. {$ENDIF}
  21.  
  22. {++++++++++++++++++++++++++++++++} INTERFACE {+++++++++++++++++++++++++++++++}
  23.  
  24. uses DOS, CRT, GoldHard;
  25.  
  26. const
  27.    GStuffBufferSize = 30;
  28.    GUpperCharSet = ['A'..'Z'];
  29.    GLowerCharSet = ['a'..'z'];
  30.    GPuncCharSet  = [',',';',':','.',' '];
  31.  
  32.    ContextMenu = 1000;
  33.    ContextList = 2000;
  34.    ContextIO   = 3000;
  35.    ContextDir  = 4000;
  36.    ContextCalc = 5000;
  37.    ContextCal  = 6000;
  38.  
  39. type
  40.    HelpRecord = record
  41.       Context: word;
  42.       ID: word;
  43.       case word of           {variant record}
  44.       0: (HelpPtr: pointer);
  45.       1: (HelpLong: longint);
  46.       2: (HelpChar: char);
  47.    end;
  48.  
  49. {$IFDEF TTT5}
  50.    Key_Pressed_Type = procedure(var Ch:char);
  51. {$ENDIF}
  52.  
  53.    KeyIdleHook = procedure;
  54.    KeyPressedHook = procedure(var Code:word; var X,Y:byte);
  55.    KeyHelpHook = procedure(Context:word; HelpInfo: HelpRecord);
  56.  
  57.    KeySet = record
  58.       LastECode: integer;
  59.       {mouse data}
  60.       ButtonCount: byte;     {0 means no mouse installed}
  61.       MouseActive: boolean;
  62.       RightHanded: boolean;
  63.       MouseVisible: boolean;
  64.       MouseWasVisible: boolean;
  65.       DoubleDelay: integer;
  66.       {keyboard data}
  67.       Click: boolean;           {click after every keypress?}
  68.       Buffer: array[1..GStuffBufferSize] of word;
  69.       BufferHead: word;         {next character from buffer}
  70.       BufferTail: word;         {last valid character in buffer}
  71.       LastKey: word;            {the last key pressed}
  72.       LastX:byte;               {location of mouse when button pressed}
  73.       LastY:byte;               {                -"-                  }
  74.       IdleHook: KeyIdleHook;
  75.       PressedHook: KeyPressedHook;
  76.       HelpHook: KeyHelpHook;
  77.       Time: Longint;            {the time the last key was processed}
  78.       Extended : boolean;       {is it an extended keyboard}
  79.       InitScrollDelay: integer;
  80.       ScrollDelay: integer;
  81.       HelpKey: word;
  82.    end;
  83.  
  84. var
  85.    KeyVars: KeySet;
  86.  
  87. {mouse routines}
  88. function  MouseInstalled:boolean;
  89. procedure MouseHardwareReset;
  90. procedure MouseSoftwareReset;
  91. procedure MouseShow(On:boolean);
  92. procedure MouseMove(X,Y: integer);
  93. procedure MouseConfine(X1,Y1,X2,Y2:integer);
  94. procedure MousePos(var X,Y : byte);
  95. function  MouseReleased(Button: integer; var X,Y: byte): byte;
  96. function  MousePressed(Button: integer; var X,Y: byte): byte;
  97. function  MouseInZone(X1,Y1,X2,Y2: byte):boolean;
  98. procedure MouseStatus(var L,C,R:boolean; var X,Y : byte);
  99. procedure MouseStatusWin(var L,C,R:boolean; var X,Y : byte);
  100. procedure MouseStyle(OrdChar,Attr: byte);
  101. procedure MouseRelease;
  102. {buffer routines}
  103. procedure KeyFlushBuffer;
  104. function  KeyBufferSpace:word;
  105. procedure KeyStuffBuffer(W:word);
  106. procedure KeyStuffBufferMouse(W:word;X,Y:byte);
  107. procedure KeyStuffBufferStr(Str:string);
  108. {hook routines}
  109. procedure AssignPressedHook(Hook:KeyPressedHook);
  110. procedure AssignIdleHook(Hook:KeyIdleHook);
  111. procedure AssignHelpHook(Hook:KeyHelpHook);
  112. procedure CallForHelp(Context:word; HelpInfo: HelpRecord);
  113. {key routines}
  114. procedure NoKeyIdleHook;
  115. procedure NoKeyPressedHook(var W:word; var X,Y:byte);
  116. function  WordToChar(W:word):char;
  117. function  GKeyPressed:boolean;
  118. function  KeyorMousePressed: boolean;
  119. function  ExtendedKeyBoard:boolean;
  120. {key reading procs}
  121. function  GetKey:char;
  122. procedure GetInput;
  123. procedure GetInputRel;
  124. procedure GetInputWait(WaitTime:longint);
  125. procedure DelayKey(WaitTime:longint);
  126. function  KeyGetTime: longint;
  127. {keyboard properties}
  128. procedure KeySetSlow;
  129. procedure KeySetFast;
  130. procedure KeySetRepeatRate(Delay,Rate:byte);
  131. {auxilary keys}
  132. function  KeyShiftPressed: boolean;
  133. function  KeyRightShiftPressed: boolean;
  134. function  KeyLeftShiftPressed: boolean;
  135. function  KeyCtrlPressed:boolean;
  136. function  KeyAltPressed:boolean;
  137. function  KeyGetScroll:boolean;
  138. function  KeyGetNum:boolean;
  139. function  KeyGetCaps:boolean;
  140. procedure KeySetScroll(On:boolean);
  141. procedure KeySetNum(On:boolean);
  142. procedure KeySetCaps(On:boolean);
  143. procedure KeySetClicking(Clicking : boolean);
  144. {help routines}
  145.  
  146. {$IFDEF TTT5}
  147.  
  148. procedure No_Idle_Hook;
  149. procedure No_Pressed_Hook(var Ch:char);
  150. procedure Assign_Idle_Hook(PassedProc : KeyIdleHook);
  151. procedure Set_Clicking(Clicking : boolean);
  152. procedure Default_Settings;
  153. function  Mouse_Installed:Boolean;
  154. procedure Show_Mouse_Cursor;
  155. procedure Hide_Mouse_Cursor;
  156. procedure Move_Mouse(Hor,Ver: integer);
  157. procedure Confine_Mouse_Horiz(Left,Right:integer);
  158. procedure Confine_Mouse_Vert(Top,Bot:integer);
  159. procedure Set_Mouse_Cursor_Style(OrdChar: integer);
  160. function  Alt_Pressed:Boolean;
  161. function  Ctrl_Pressed:Boolean;
  162. function  LeftShift_Pressed: Boolean;
  163. function  RightShift_Pressed: Boolean;
  164. function  Shift_Pressed: Boolean;
  165. function  CapsOn: Boolean;
  166. function  NumOn: Boolean;
  167. function  ScrollOn: Boolean;
  168. procedure Set_Caps(On : boolean);
  169. procedure Set_Num(On : boolean);
  170. procedure Set_Scroll(On : boolean);
  171. procedure FlushKeyBuffer;
  172.  
  173. {$ENDIF}
  174.  
  175. {+++++++++++++++++++++++++++++} IMPLEMENTATION {+++++++++++++++++++++++++++++}
  176. uses GoldFast;
  177.  
  178. const
  179.    MouseInt = $33;
  180.    KeyInt = $16;
  181.    ClockTicks = 18.2;
  182.  
  183. var
  184.    KeyStatusBits: ^word;
  185.    DOSBufferHead: ^word;
  186.    DOSBufferTail: ^word;
  187.  
  188. function LastKeyError: integer;
  189. {}
  190. begin
  191.    LastKeyError := KeyVars.LastEcode;
  192. end; { LastKeyError }
  193.  
  194.                           {**********************}
  195.                           {**  Mouse Routines  **}
  196.                           {**********************}
  197.  
  198. function MouseInstalled:boolean;
  199. {}
  200. var
  201.   MouseInterruptPtr: pointer;
  202.   Reg: registers;
  203.   Installed: boolean;
  204. begin
  205.    MouseInterruptPtr := ptr($0000,$00CC);
  206.    if (MouseInterruptPtr = nil)
  207.    or (byte(MouseInterruptPtr) = $CF) then
  208.       Installed := false          {don't call interrupt if vector is zero}
  209.    else with KeyVars do
  210.    begin
  211.       Reg.Ax := $21;
  212.       Intr($33,Reg);
  213.       Installed :=  Reg.Ax = $FFFF;
  214.       if Installed then
  215.          ButtonCount := Reg.Bx
  216.       else
  217.          ButtonCount := 0;
  218.    end;
  219.    MouseInstalled := Installed;
  220. end; { MouseInstalled }
  221.  
  222. procedure MouseHardwareReset;
  223. {}
  224. var Regs: registers;
  225. begin
  226.    if KeyVars.MouseActive then
  227.    begin
  228.       Regs.Ax := $00;
  229.       Intr(MouseInt,Regs);
  230.       KeyVars.ButtonCount := Regs.Bx;
  231.       KeyVars.MouseVisible := false;
  232.    end;
  233. end; { MouseHardwareReset }
  234.  
  235. procedure MouseSoftwareReset;
  236. {}
  237. var Regs: registers;
  238. begin
  239.    if KeyVars.MouseActive then
  240.    begin
  241.       Regs.Ax := $21;
  242.       Intr(MouseInt,Regs);
  243.       KeyVars.ButtonCount := Regs.Bx;
  244.       KeyVars.MouseVisible := false;
  245.    end;
  246. end; { MouseSoftwareReset }
  247.  
  248. procedure MouseShow(On:boolean);
  249. {}
  250. var Regs: registers;
  251. begin
  252.    if KeyVars.MouseActive then
  253.    begin
  254.       if On then
  255.          Regs.Ax := $01
  256.       else
  257.          Regs.Ax := $02;
  258.       KeyVars.MouseVisible := On;
  259.       Intr(MouseInt,Regs);
  260.    end;
  261. end; { MouseShow }
  262.  
  263. procedure MouseMove(X,Y: integer);
  264. {X and Y are character positions not pixel positions}
  265. var Regs: registers;
  266. begin
  267.    if KeyVars.MouseActive then
  268.    begin
  269.       with Regs do
  270.       begin
  271.          Ax := $04;
  272.          Cx := pred(X*8);   {8 pixels per character}
  273.          Dx := pred(Y*8);   {         "-"          }
  274.       end; {with}
  275.       Intr(MouseInt,Regs);
  276.    end;
  277. end; { MouseMove }
  278.  
  279. procedure MouseConfine(X1,Y1,X2,Y2:integer);
  280. {}
  281. var Regs: registers;
  282. begin
  283.    if KeyVars.MouseActive then
  284.       with Regs do
  285.       begin
  286.          {horizontal}
  287.          Ax := $07;
  288.          Cx := pred(X1*8);
  289.          Dx := pred(X2*8);
  290.          intr(MouseInt,Regs);
  291.          {vertical}
  292.          Ax := $08;
  293.          Cx := pred(Y1*8);
  294.          Dx := pred(Y2*8);
  295.          intr(MouseInt,Regs);
  296.       end;
  297. end; { MouseConfine }
  298.  
  299. procedure MousePos(var X,Y : byte);
  300. {}
  301. var Regs: registers;
  302. begin
  303.    if KeyVars.MouseActive then
  304.       with Regs do
  305.       begin
  306.          Ax := 3;
  307.          intr(MouseInt,Regs);
  308.          X := succ(Cx div 8);
  309.          Y := succ(Dx div 8);
  310.       end; {with}
  311. end; { MousePos }
  312.  
  313. function AdjustedButton(Button:integer):integer;
  314. {used internally to swap the role of left and right buttons}
  315. begin
  316.    if (KeyVars.RightHanded = false) or (Button > 2) then
  317.       AdjustedButton := Button
  318.    else
  319.       AdjustedButton := ord(Button = 0);
  320. end; { AdjustedButton }
  321.  
  322. function MouseReleased(Button: integer; var X,Y: byte): byte;
  323. {}
  324. var Regs: registers;
  325. begin
  326.    if KeyVars.MouseActive then
  327.    begin
  328.       with Regs do
  329.       begin
  330.          Ax := 6;
  331.          Bx := AdjustedButton(Button);
  332.          intr(MouseInt,Regs);
  333.          MouseReleased := Bx;
  334.          X := succ(Cx div 8);
  335.          Y := succ(Dx div 8);
  336.       end;
  337.    end
  338.    else
  339.       MouseReleased := 0;
  340. end; { MouseReleased }
  341.  
  342. function MousePressed(Button: integer; var X,Y: byte): byte;
  343. {}
  344. var Regs: registers;
  345. begin
  346.    if KeyVars.MouseActive then
  347.    begin
  348.       with Regs do
  349.       begin
  350.          Ax := 5;
  351.          Bx := AdjustedButton(Button);
  352.          intr(MouseInt,Regs);
  353.          MousePressed := Bx;
  354.          X := succ(Cx div 8);
  355.          Y := succ(Dx div 8);
  356.       end;
  357.    end else
  358.       MousePressed := 0;
  359. end; { MousePressed }
  360.  
  361. procedure ClearMouseBuffers;
  362. {}
  363. var Regs: registers;
  364. begin
  365.    if KeyVars.MouseActive then
  366.    begin
  367.       with Regs do
  368.       begin
  369.          Ax := 5; Bx := 0; intr(MouseInt,Regs);
  370.          Ax := 5; Bx := 1; intr(MouseInt,Regs);
  371.          Ax := 6; Bx := 0; intr(MouseInt,Regs);
  372.          Ax := 6; Bx := 1; intr(MouseInt,Regs);
  373.          if KeyVars.ButtonCount = 3 then
  374.          begin
  375.             Ax := 5; Bx := 2; intr(MouseInt,Regs);
  376.             Ax := 6; Bx := 2; intr(MouseInt,Regs);
  377.          end;
  378.       end;
  379.    end;
  380. end; { ClearMouseBuffers }
  381.  
  382. function MouseInZone(X1,Y1,X2,Y2: byte): boolean;
  383. {}
  384. var X,Y: byte;
  385. begin
  386.    if KeyVars.MouseActive and KeyVars.MouseVisible then
  387.    begin
  388.       MousePos(X,Y);
  389.       MouseInZone := (X >= X1) and (X <= X2) and (Y >= Y1) and (Y <= Y2);
  390.    end else
  391.       MouseInZone := false;
  392. end; { MouseInZone }
  393.  
  394. procedure MouseStatus(var L,C,R: boolean; var X,Y: byte);
  395. {}
  396. var Regs: registers;
  397. begin
  398.    if KeyVars.MouseActive then
  399.    begin
  400.       with Regs do
  401.       begin
  402.          Ax := 3;
  403.          intr(MouseInt,Regs);
  404.          X := succ(Cx div 8);
  405.          Y := succ(Dx div 8);
  406.          if not KeyVars.RightHanded then
  407.          begin
  408.             L := ((BX and $01) = $01);
  409.             R := ((BX and $02) = $02);
  410.          end else
  411.          begin
  412.             R := ((BX and $01) = $01);
  413.             L := ((BX and $02) = $02);
  414.          end;
  415.          C := ((BX and $04) = $04);
  416.       end; {with}
  417.    end else
  418.    begin
  419.       L := false;
  420.       C := false;
  421.       R := false;
  422.       X := 1;
  423.       Y := 1;
  424.    end;
  425. end; { MouseStatus }
  426.  
  427. procedure MouseStatusWin(var L,C,R: boolean; var X,Y: byte);
  428. {Like MouseStatus, But X and Y are local to the Window}
  429. begin
  430.    MouseStatus(L,C,R,X,Y);
  431.    if (VideoTarget.TargetType = WinTarget) then
  432.    begin
  433.       dec(X,pred(WStructurePtr(VideoTarget.TargetPtr)^.X));
  434.       dec(Y,pred(WStructurePtr(VideoTarget.TargetPtr)^.Y));
  435.    end;
  436.    if VideoTarget.WindowActive then
  437.    begin
  438.       dec(X,pred(VideoTarget.WX1));
  439.       dec(Y,pred(VideoTarget.WY1));
  440.    end;
  441. end; { MouseStatusWin }
  442.  
  443. procedure MouseStyle(OrdChar,Attr: byte);
  444. {changes the style of the floating mouse cursor}
  445. var
  446.   Regs: registers;
  447. begin
  448.    if KeyVars.MouseActive then
  449.    begin
  450.       Regs.Ax := 10;
  451.       Regs.Bx := 0;        {software text cursor}
  452.       if Attr = 0 then
  453.          Regs.CX := $7700
  454.       else
  455.          Regs.Cx := $00;
  456.       Regs.Dl := OrdChar;
  457.       Regs.Dh := Attr;
  458.       Intr(MouseInt,Regs);
  459.    end;
  460. end; { MouseStyle }
  461.  
  462. procedure MouseRelease;
  463. {Waits for all mouse buttons to be released and clears the
  464.  pressed history}
  465. var
  466.   L,M,R: boolean;
  467.   X,Y,P: byte;
  468. begin
  469.    repeat
  470.       MouseStatus(L,M,R,X,Y);
  471.    until not L and not M and not R;
  472.    P := MouseReleased(0,X,Y);
  473.    P := MouseReleased(1,X,Y);
  474.    if KeyVars.ButtonCount > 2 then
  475.       P := MouseReleased(2,X,Y);
  476. end; { MouseRelease }
  477.  
  478.                         {*************************}
  479.                         {**  Keyboard Routines  **}
  480.                         {*************************}
  481.  
  482. {$IFOPT F-}
  483.    {$DEFINE FOFF}
  484.    {$F+}
  485. {$ENDIF}
  486.  procedure NoKeyIdleHook;
  487.  {empty procs}
  488.  begin end; {NoKeyIdleHook}
  489.  
  490.  procedure NoKeyPressedHook(var W:word; var X,Y:byte);
  491.  {empty procs}
  492.  begin end; {NoKeyPressedHook}
  493.  
  494.  procedure NoHelpHook(Context:word; HelpInfo: HelpRecord);
  495.  {empty procs}
  496.  begin end; {NoHelpHook}
  497. {$IFDEF FOFF}
  498.    {$F-}
  499.    {$UNDEF FOFF}
  500. {$ENDIF}
  501.  
  502. procedure AssignPressedHook(Hook:KeyPressedHook);
  503. {}
  504. begin
  505.    KeyVars.PressedHook := Hook;
  506. end; { AssignPressedHook }
  507.  
  508. procedure AssignIdleHook(Hook:KeyIdleHook);
  509. {}
  510. begin
  511.    KeyVars.IdleHook := Hook;
  512. end; { AssignIdleHook }
  513.  
  514. procedure AssignHelpHook(Hook:KeyHelpHook);
  515. {}
  516. begin
  517.    KeyVars.helpHook := Hook;
  518. end; { AssignHelpHook }
  519.  
  520. function WordToChar(W:word):char;
  521. {}
  522. begin
  523.    If W > 255 then
  524.       WordToChar := #0
  525.    else
  526.       WordToChar := chr(W);
  527. end; { WordToChar }
  528.  
  529. function KeyorMousePressed:boolean;
  530. {}
  531. var
  532.    L,C,R:boolean;
  533.    X,Y : byte;
  534. begin
  535.    MouseStatus(L,C,R,X,Y);
  536.    with KeyVars do
  537.      KeyorMousePressed :=  (BufferHead <> BufferTail)
  538.                             or
  539.                            (DOSBufferHead^ <> DOSBufferTail^)
  540.                             or L or R or C;
  541. end; { KeyorMousePressed }
  542.  
  543. function GKeyPressed:boolean;
  544. {}
  545. begin
  546.    with KeyVars do
  547.      GKeyPressed :=  (BufferHead <> BufferTail)
  548.                      or
  549.                      (DOSBufferHead^ <> DOSBufferTail^);
  550. end; { GKeyPressed }
  551.  
  552. function ExtendedKeyBoard:boolean;
  553. {}
  554. var Regs: registers;
  555. begin
  556.    ExtendedKeyBoard := false;
  557.    Regs.Ah := $12;
  558.    intr(KeyInt,Regs);
  559.    if Regs.Al = KeyStatusBits^ then {might be extended}
  560.    begin
  561.       KeyStatusBits^ := KeyStatusBits^ XOR $20;
  562.       Regs.Ah := $12;
  563.       intr(KeyInt,Regs);
  564.       ExtendedkeyBoard := Regs.Al = KeyStatusBits^;
  565.       KeyStatusBits^ := KeyStatusBits^ XOR $20;
  566.    end;
  567. end; { ExtendedKeyBoard }
  568.  
  569. procedure KeySetCaps(On:boolean);
  570. {}
  571. begin
  572.    if On then
  573.       KeyStatusBits^ := (KeyStatusBits^ or $40)
  574.    else
  575.       KeyStatusBits^ := (KeyStatusBits^ and $BF);
  576. end; { KeySetCaps }
  577.  
  578. procedure KeySetNum(On:boolean);
  579. {}
  580. begin
  581.    if On then
  582.       KeyStatusBits^ := (KeyStatusBits^ or $20)
  583.    else
  584.       KeyStatusBits^ := (KeyStatusBits^ and $DF);
  585. end; { KeySetNum }
  586.  
  587. procedure KeySetScroll(On:boolean);
  588. {}
  589. begin
  590.    if On then
  591.       KeyStatusBits^ := (KeyStatusBits^ or $10)
  592.    else
  593.       KeyStatusBits^ := (KeyStatusBits^ and $EF);
  594. end; { KeySetScroll }
  595.  
  596. function KeyGetCaps:boolean;
  597. {}
  598. var CapsOnW: word;
  599. begin
  600.    CapsOnW := swap(KeyStatusBits^);
  601.    KeyGetCaps := (CapsOnW and $4000) <> 0;
  602. end; { KeyGetCaps }
  603.  
  604. function KeyGetNum:boolean;
  605. {}
  606. var NumOnW: word;
  607. begin
  608.    NumOnW := swap(KeyStatusBits^);
  609.    KeyGetNum := (NumOnW and $2000) <> 0;
  610. end; { KeyGetNum }
  611.  
  612. function KeyGetScroll:boolean;
  613. {}
  614. var ScrollOnW: word;
  615. begin
  616.    ScrollOnW := swap(KeyStatusBits^);
  617.    KeyGetScroll := (ScrollOnW and $1000) <> 0;
  618. end; { KeyGetScroll }
  619.  
  620. function KeyAltPressed:boolean;
  621. var
  622.   AltW: word;
  623. begin
  624.    AltW := swap(KeyStatusBits^);
  625.    KeyAltPressed := (AltW and $0800) <> 0;
  626. end; { KeyAltPressed }
  627.  
  628. function KeyCtrlPressed:boolean;
  629. var
  630.   CtrlW: word;
  631. begin
  632.    CtrlW := swap(KeyStatusBits^);
  633.    KeyCtrlPressed := (CtrlW and $0400) <> 0;
  634. end; { KeyCtrlPressed }
  635.  
  636. function KeyLeftShiftPressed: boolean;
  637. {}
  638. var LSW: word;
  639. begin
  640.    LSW := swap(KeyStatusBits^);
  641.    KeyLeftShiftPressed := (LSW and $0200) <> 0;
  642. end; { KeyLeftShiftPressed }
  643.  
  644. function KeyRightShiftPressed: boolean;
  645. {}
  646. var RSW: word;
  647. begin
  648.    RSW := swap(KeyStatusBits^);
  649.    KeyRightShiftPressed := (RSW and $0100) <> 0;
  650. end; { KeyRightShiftPressed }
  651.  
  652. function KeyShiftPressed: boolean;
  653. {}
  654. var SW: word;
  655. begin
  656.    SW := swap(KeyStatusBits^);
  657.    KeyShiftPressed := ((SW and $0200) <> 0) or ((SW and $0100) <> 0);
  658. end; { KeyShiftPressed }
  659.  
  660. procedure KeySetRepeatRate(Delay,Rate:byte);
  661. {}
  662. var Regs: registers;
  663. begin
  664.    with Regs do
  665.    begin
  666.       Ah := 3;
  667.       Al := 5;
  668.       Bl := Rate;
  669.       Bh := pred(Delay);
  670.    end;
  671.    Intr(KeyInt,Regs);
  672. end; { KeySetRepeatRate }
  673.  
  674. procedure KeySetFast;
  675. {}
  676. begin
  677.    KeySetRepeatRate(1,0);
  678. end; { KeySetFast }
  679.  
  680. procedure KeySetSlow;
  681. {}
  682. begin
  683.    KeySetRepeatRate(2,$14);
  684. end; { KeySetSlow }
  685.  
  686. procedure KeyClick;
  687. {INTERNAL}
  688. begin
  689.    sound(1000);
  690.    sound(50);
  691.    delay(5);
  692.    nosound;
  693. end; { KeyClick }
  694.  
  695. function KeyExtendedKey(var K:byte):boolean;
  696. {INTERNAL}
  697. var Regs: registers;
  698. begin
  699.    with Regs do
  700.    begin
  701.       if KeyVars.Extended then
  702.          Ah := $10
  703.       else
  704.          Ah := $0;
  705.       intr(KeyInt,Regs);
  706.       if (Al = 0) or (Al = $E0) then
  707.       begin
  708.          K := Ah;
  709.          KeyExtendedKey := true;
  710.       end else
  711.       begin
  712.          K := Al;
  713.          KeyExtendedKey := false;
  714.       end;
  715.    end;
  716. end; { KeyExtendedKey }
  717.  
  718. function KeyReadKey: char;
  719. const ch: char = #0;
  720. var K: byte;
  721. begin
  722.    if Ch = #0 then
  723.    begin
  724.      if KeyExtendedKey(K) then
  725.       begin
  726.          KeyReadkey := Ch;
  727.          Ch := chr(K);
  728.       end else
  729.       begin
  730.          KeyReadKey := chr(K);
  731.          Ch := #0;
  732.       end;
  733.    end else
  734.    begin
  735.       KeyReadkey := Ch;
  736.       Ch := #0;
  737.    end;
  738. end; { KeyReadKey }
  739.  
  740. function KeyBufferSpace:word;
  741. {}
  742. begin
  743.    with KeyVars do
  744.       KeyBufferSpace := GStuffBufferSize - abs(BufferTail-BufferHead);
  745. end; { KeyBufferSpace }
  746.  
  747. procedure KeyFlushBuffer;
  748. {}
  749. var Regs: registers;
  750. begin
  751.    with KeyVars do
  752.       BufferTail := BufferHead; {empty program buffer}
  753.    with Regs do
  754.    begin
  755.       Ax := ($0C shl 8) or 6;
  756.       Dx := $00FF;
  757.    end;
  758.    Intr($21,Regs);
  759. end; { KeyFlushBuffer }
  760.  
  761. procedure KeyFlushDOSBuffer;
  762. var Regs : registers;
  763. begin
  764.    with Regs do
  765.    begin
  766.        Ax := ($0c shl 8) or 6;
  767.        Dx := $00ff;
  768.    end;
  769.    Intr($21,Regs);
  770. end;  { KeyFlushDOSBuffer }
  771.  
  772. procedure KeyStuffBuffer(W:word);
  773. {adds word to program input buffer}
  774. begin
  775.    with KeyVars do
  776.    begin
  777.       if (BufferTail + 1 = BufferHead)
  778.       or ((BufferTail = GStuffBufferSize) and (BufferHead = 1)) then
  779.          exit; {buffer full}
  780.       Buffer[BufferTail] := W;
  781.       if BufferTail < GStuffBufferSize then
  782.          inc(BufferTail)
  783.       else
  784.          BufferTail := 1;
  785.    end;
  786. end; { KeyStuffBuffer }
  787.  
  788. procedure KeyStuffBufferMouse(W:word;X,Y:byte);
  789. {adds a mouse press and mouse coords to the buffer}
  790. begin
  791.    KeyStuffBuffer(W);
  792.    KeyStuffBuffer(X);
  793.    KeyStuffBuffer(Y);
  794. end; { KeyStuffBufferMouse }
  795.  
  796. function KeyGetTime: longint;
  797. {}
  798. var T: longint;
  799. begin
  800. {$IFDEF DPMI}
  801.    T := MemL[Seg0040:$006C];
  802. {$ELSE}
  803.    T := MemL[$0040:$006C];
  804. {$ENDIF}
  805.    KeyGetTime := T;
  806. end; { KeyGetTime }
  807.  
  808. procedure KeyStuffBufferStr(Str:string);
  809. {}
  810. var I,L: byte;
  811. begin
  812.    if Str <> '' then
  813.    begin
  814.       I := 1;
  815.       L := length(Str);
  816.       if L > GStuffBufferSize then
  817.          L := GStuffBufferSize;
  818.       while I <= L do
  819.       begin
  820.          KeyStuffBuffer(ord(Str[I]));
  821.          inc(I);
  822.       end;
  823.    end;
  824. end; { KeyStuffBufferStr }
  825.  
  826. procedure KeyGetInputEngine;
  827. {waits for a keypress or mouse activity - exits when keypressed
  828.  or when a mouse button is pressed DOWN}
  829. var
  830.    L,C,R,
  831.    Finished: boolean;
  832.    Ch: char;
  833.    Keyword: word;
  834.    X,Y: byte;
  835.    ThisTime: longint;
  836.  
  837.    procedure MoveBufferHead;
  838.    begin
  839.       with KeyVars do
  840.          if BufferHead < GStuffBufferSize then
  841.             inc(BufferHead)
  842.          else
  843.             BufferHead := 1;
  844.    end; { MoveBufferHead }
  845.  
  846.    function ReadFromBuffer:boolean;
  847.    begin
  848.       with KeyVars do
  849.          if BufferHead <> BufferTail then  {read from buffer}
  850.          begin
  851.             Keyword := Buffer[BufferHead];
  852.             MoveBufferHead;
  853.             if (KeyWord >= 513) and (KeyWord <= 525) then
  854.             begin
  855.                X := Buffer[BufferHead];
  856.                MoveBufferHead;
  857.                Y := Buffer[BufferHead];
  858.                MoveBufferHead;
  859.             end;
  860.             ReadFromBuffer := true;
  861.          end else
  862.            ReadFromBuffer := false;
  863.    end; { ReadFromBuffer }
  864.  
  865.    procedure CheckButtonCombos;
  866.    {Checks to see if Alt Ctrl or Shift are pressed while mouse down}
  867.    begin
  868.       if KeyAltPressed then
  869.          inc(Keyword)
  870.       else if KeyCtrlPressed then
  871.          inc(Keyword,2)
  872.       else if KeyShiftPressed then
  873.          inc(Keyword,3);
  874.    end; { CheckButtonCombos }
  875.  
  876. begin
  877.    if not ReadFromBuffer then
  878.    begin
  879.       Finished := false;
  880.       repeat
  881.          KeyVars.IdleHook;       {call the users idle hook procedure}
  882.          if ReadFromBuffer then  {see if user's hook stuffed the buffer}
  883.             Finished := true
  884.          else if KeyVars.MouseActive then
  885.          begin
  886.             Keyword := 0;
  887.             MouseStatus(L,C,R,X,Y);
  888.             if L then
  889.                KeyWord := 500      {left button down}
  890.             else if R then
  891.                KeyWord := 504      {right button down}
  892.             else if C then
  893.                KeyWord := 508;     {middle button down}
  894.             CheckButtonCombos;
  895.             ThisTime := KeyGetTime;
  896.             if (KeyVars.LastX = X)  {mouse in same place}
  897.             and (KeyVars.LastY = Y)
  898.             and (L or C or R)
  899.             and ((KeyWord = KeyVars.Lastkey) or (KeyWord+20 = KeyVars.Lastkey))
  900.             and ((ThisTime - KeyVars.Time) <= (KeyVars.DoubleDelay div 55)) then
  901.                inc(KeyWord,40);     {make it a double!}
  902.             if L or R or C then    {a button is being depressed}
  903.                Finished := true;
  904.          end;
  905.       until Finished or GKeyPressed;
  906.       if not Finished then
  907.       begin
  908.          Ch := KeyReadKey;
  909.          if Ch = #0 then
  910.          begin
  911.             Ch := KeyReadkey;
  912.             Keyword := 256+ord(Ch);
  913.             if (KeyWord >= 327) and (Keyword <= 339) then
  914.             begin
  915.                if KeyAltPressed then
  916.                   inc(Keyword,80)
  917.                else if (KeyShiftPressed and KeyVars.Extended) then
  918.                   case Keyword of    {fix for George's BIOS!}
  919.                      338: Keyword := 261;
  920.                      339: Keyword := 263;
  921.                      9: Keyword := 271;
  922.                   else
  923.                      inc(Keyword,100)
  924.                   end {case}
  925.                else if KeyCtrlPressed then
  926.                   inc(Keyword,120);
  927.             end;
  928.         end else
  929.            KeyWord := ord(Ch);
  930.       end;
  931.    end;
  932.    with KeyVars do
  933.    begin
  934.       Time := KeyGetTime;
  935.       LastKey := Keyword;
  936.       LastX := X;
  937.       LastY := Y;
  938.       if Click then
  939.          KeyClick;
  940.    end;
  941. end; { KeyGetInputEngine }
  942.  
  943. procedure GetInput;
  944. {}
  945. begin
  946.    KeyGetInputEngine;
  947.    with KeyVars do
  948.        PressedHook(LastKey,LastX,LastY)
  949. end; { GetInput }
  950.  
  951. procedure GetInputRel;
  952. {}
  953. var L,R,M : boolean;
  954. begin
  955.    KeyGetInputEngine;
  956.    with KeyVars do
  957.    begin
  958.       if (LastKey >= 500) and (LastKey <= 511) then
  959.       begin
  960.          MouseRelease;
  961.          inc(Lastkey,20);
  962.          MouseStatus(L,M,R,LastX,LastY);
  963.       end;
  964.       PressedHook(LastKey,LastX,LastY);
  965.    end;
  966. end; {GetInputRel}
  967.  
  968. procedure GetInputWait(WaitTime:longint);
  969. {Waits for input, but returns a zero if the specified elapsed time has passed.
  970. If the WaitTime is passed as zero, the routine will wait indefinitely.
  971. }
  972. var
  973.    L,M,R: boolean;
  974.    X,Y: byte;
  975.    StartTime: longint;
  976. begin
  977.    StartTime := KeyGetTime;
  978.    repeat
  979.       KeyVars.IdleHook;        {call the users idle hook procedure}
  980.       MouseStatus(L,M,R,X,Y);
  981.    until L or M or R or GkeyPressed
  982.    or ( (WaitTime <> 0) and (((KeyGetTime - StartTime) / ClockTicks)*1000 > WaitTime));
  983.    if not L and not M and not R and not Gkeypressed then
  984.       KeyVars.Lastkey := 0
  985.    else
  986.       GetInput;
  987. end; { GetInputWait }
  988.  
  989. function GetKey:char;
  990. {Waits for keyboard activity and returns the char pressed}
  991. begin
  992.    repeat
  993.      GetInput;
  994.    until (KeyVars.LastKey >= 13) and (KeyVars.LastKey <= 255);
  995.    GetKey := char(KeyVars.LastKey);
  996. end; { GetInput }
  997.  
  998. procedure DelayKey(WaitTime:longint);
  999. {Pauses for the user to click a mouse button, press a key, or for a specified
  1000. time to elapse. If the WaitTime is passed as zero, the routine will wait
  1001. indefinitely. The KeyVars entry is *not* updated with the key.}
  1002. var
  1003.    L,M,R: boolean;
  1004.    X,Y: byte;
  1005.    StartTime: longint;
  1006. begin
  1007.    StartTime := KeyGetTime;
  1008.    repeat
  1009.       KeyVars.IdleHook;        {call the users idle hook procedure}
  1010.       MouseStatus(L,M,R,X,Y);
  1011.    until L or M or R or GkeyPressed
  1012.    or ( (WaitTime > 0) and (((KeyGetTime - StartTime) / ClockTicks)*1000 > WaitTime));
  1013.    if L or M or R then
  1014.       MouseRelease;
  1015.    KeyFlushBuffer;
  1016. end; { DelayKey }
  1017.  
  1018. procedure KeySetClicking(Clicking : boolean);
  1019. {}
  1020. begin
  1021.    KeyVars.Click := Clicking;
  1022. end; { KeySetClicking }
  1023.  
  1024.                           {*********************}
  1025.                           {**  Help Routines  **}
  1026.                           {*********************}
  1027.  
  1028. procedure CallForHelp(Context:word; HelpInfo: HelpRecord);
  1029. {}
  1030. begin
  1031.    if @KeyVars.HelpHook <> nil then
  1032.       KeyVars.HelpHook(Context,HelpInfo);
  1033. end; { CallForHelp }
  1034.  
  1035.               {*********************************************}
  1036.               {**  U N I T   I N I T I A L I Z A T I O N  **}
  1037.               {*********************************************}
  1038. procedure KeyDefaultSettings;
  1039. {}
  1040. begin
  1041.    with KeyVars do
  1042.    begin
  1043.       RightHanded := false;
  1044.       DoubleDelay := 350;
  1045.       Click := false;
  1046.       InitScrollDelay := 350;
  1047.       ScrollDelay := 50;
  1048.       HelpKey := 315;  {F1}
  1049.       IdleHook := NoKeyIdleHook;
  1050.       PressedHook := NoKeyPressedHook;
  1051.       HelpHook := NoHelpHook;
  1052.    end;
  1053. end; { KeyDefaultSettings }
  1054.  
  1055. procedure GoldKeyInit;
  1056. {}
  1057. begin
  1058. {$IFDEF DPMI}
  1059.     KeyStatusBits := ptr(seg0040,$0017);
  1060.     DOSBufferHead := ptr(seg0040,$001A);
  1061.     DOSBufferTail := ptr(seg0040,$001C);
  1062. {$ELSE}
  1063.     KeyStatusBits := ptr($0040,$0017);
  1064.     DOSBufferHead := ptr($0040,$001A);
  1065.     DOSBufferTail := ptr($0040,$001C);
  1066. {$ENDIF}
  1067.    with KeyVars do
  1068.    begin
  1069.       LastECode := 0;
  1070.       MouseActive := MouseInstalled;
  1071.       MouseVisible := false;
  1072.       BufferHead := 1;
  1073.       BufferTail := 1;
  1074.       LastKey := 0;
  1075.       LastX := 0;
  1076.       LastY := 0;
  1077.       Extended := ExtendedKeyBoard;
  1078.    end;
  1079.    KeyDefaultSettings;
  1080. end; {GoldKeyInit}
  1081.  
  1082. {$IFDEF TTT5}
  1083.  
  1084. {$IFOPT F-}
  1085.    {$DEFINE FOFF}
  1086.    {$F+}
  1087. {$ENDIF}
  1088.  
  1089. procedure No_Idle_Hook;
  1090. {included for TTT5 compatibility}
  1091. begin
  1092.    { abstract } {NoKeyIdleHook;}
  1093. end; { No_Idle_Hook }
  1094.  
  1095. procedure No_Pressed_Hook(var Ch:char);
  1096. {included for TTT5 compatibility}
  1097. begin
  1098.    { abstract } {NoKeyPressedHook;}
  1099. end; { No_Pressed_Hook }
  1100.  
  1101. {$IFDEF FOFF}
  1102.    {$F-}
  1103.    {$UNDEF FOFF}
  1104. {$ENDIF}
  1105.  
  1106. procedure Assign_Idle_Hook(PassedProc: KeyIdleHook);
  1107. {included for TTT5 compatibility}
  1108. begin
  1109.    AssignIdleHook(PassedProc);
  1110. end; { Assign_Idle_Hook }
  1111.  
  1112. procedure Set_Clicking(Clicking: boolean);
  1113. {included for TTT5 compatibility}
  1114. begin
  1115.    KeySetClicking(Clicking);
  1116. end; { Set_Clicking }
  1117.  
  1118. procedure Default_Settings;
  1119. {included for TTT5 compatibility}
  1120. begin
  1121.    { abstract }
  1122. end; { Default_Settings }
  1123.  
  1124. function  Mouse_Installed:boolean;
  1125. {included for TTT5 compatibility}
  1126. begin
  1127.    Mouse_Installed := MouseInstalled;
  1128. end; { Mouse_Installed }
  1129.  
  1130. procedure Show_Mouse_Cursor;
  1131. {included for TTT5 compatibility}
  1132. begin
  1133.    MouseShow(true);
  1134. end; { Show_Mouse_Cursor }
  1135.  
  1136. procedure Hide_Mouse_Cursor;
  1137. {included for TTT5 compatibility}
  1138. begin
  1139.    MouseShow(false);
  1140. end; { Hide_Mouse_Cursor }
  1141.  
  1142. procedure Move_Mouse(Hor,Ver: integer);
  1143. {included for TTT5 compatibility}
  1144. begin
  1145.    MouseMove(Hor,Ver);
  1146. end; { Move_Mouse }
  1147.  
  1148. procedure Confine_Mouse_Horiz(Left,Right:integer);
  1149. {included for TTT5 compatibility}
  1150. var Regs: registers;
  1151. begin
  1152.    if KeyVars.MouseActive then
  1153.    with Regs do
  1154.    begin
  1155.       {horizontal}
  1156.       Ax := $07;
  1157.       Cx := pred(Left*8);
  1158.       Dx := pred(Right*8);
  1159.       intr(MouseInt,Regs);
  1160.    end;
  1161. end; { Confine_Mouse_Horiz }
  1162.  
  1163. procedure Confine_Mouse_Vert(Top,Bot:integer);
  1164. {included for TTT5 compatibility}
  1165. var Regs: registers;
  1166. begin
  1167.    if KeyVars.MouseActive then
  1168.    with Regs do
  1169.    begin
  1170.       {vertical}
  1171.       Ax := $08;
  1172.       Cx := pred(Top*8);
  1173.       Dx := pred(Bot*8);
  1174.       intr(MouseInt,Regs);
  1175.    end;
  1176. end; { Confine_Mouse_Vert }
  1177.  
  1178. procedure Set_Mouse_Cursor_Style(OrdChar: integer);
  1179. {included for TTT5 compatibility}
  1180. begin
  1181.    MouseStyle(OrdChar,0);
  1182. end; { Set_Mouse_Cursor_Style }
  1183.  
  1184. function  Alt_Pressed:boolean;
  1185. {included for TTT5 compatibility}
  1186. begin
  1187.    Alt_Pressed := KeyAltPressed;
  1188. end; { Alt_Pressed }
  1189.  
  1190. function  Ctrl_Pressed:boolean;
  1191. {included for TTT5 compatibility}
  1192. begin
  1193.    Ctrl_Pressed := KeyCtrlPressed;
  1194. end; { Ctrl_Pressed }
  1195.  
  1196. function  LeftShift_Pressed: boolean;
  1197. {included for TTT5 compatibility}
  1198. begin
  1199.    LeftShift_Pressed := KeyLeftShiftPressed;
  1200. end; { LeftShift_Pressed }
  1201.  
  1202. function  RightShift_Pressed: boolean;
  1203. {included for TTT5 compatibility}
  1204. begin
  1205.    RightShift_Pressed := KeyRightShiftPressed;
  1206. end; { RightShift_Pressed }
  1207.  
  1208. function  Shift_Pressed: boolean;
  1209. {included for TTT5 compatibility}
  1210. begin
  1211.    Shift_Pressed := KeyShiftPressed;
  1212. end; { Shift_Pressed }
  1213.  
  1214. function  CapsOn: boolean;
  1215. {included for TTT5 compatibility}
  1216. begin
  1217.    CapsOn := KeyGetCaps;
  1218. end; { CapsOn }
  1219.  
  1220. function  NumOn: boolean;
  1221. {included for TTT5 compatibility}
  1222. begin
  1223.    NumOn := KeyGetNum;
  1224. end; { NumOn }
  1225.  
  1226. function  ScrollOn: boolean;
  1227. {included for TTT5 compatibility}
  1228. begin
  1229.    ScrollOn := KeyGetScroll;
  1230. end; { ScrollOn }
  1231.  
  1232. procedure Set_Caps(On : boolean);
  1233. {included for TTT5 compatibility}
  1234. begin
  1235.    KeySetCaps(On);
  1236. end; { Set_Caps }
  1237.  
  1238. procedure Set_Num(On : boolean);
  1239. {included for TTT5 compatibility}
  1240. begin
  1241.    KeySetNum(On);
  1242. end; { Set_Num }
  1243.  
  1244. procedure Set_Scroll(On : boolean);
  1245. {included for TTT5 compatibility}
  1246. begin
  1247.    KeySetScroll(On);
  1248. end; { Set_Scroll }
  1249.  
  1250. procedure FlushKeyBuffer;
  1251. {included for TTT5 compatibility}
  1252. begin
  1253.    KeyFlushDOSBuffer;
  1254. end; { FlushKeyBuffer }
  1255.  
  1256. {$ENDIF}
  1257.  
  1258. begin
  1259.    GoldKeyInit;
  1260. end.
  1261.